package com.hedl.practice.diyJava.data.local_data_time.test;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;

public class Study_LocalDateTime {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now();
        LocalTime time = LocalTime.now();
        LocalDateTime  localDateTime = LocalDateTime.now();
        System.out.println("================================================================================");

        /**
         * 日期：2023-03-02
         * 时间：17:30:17.857243
         * 本地日期时间：2023-03-02T17:30:17.857294
         */
        System.out.println("日期："+date);
        System.out.println("时间："+time);
        System.out.println("本地日期时间："+localDateTime);
        //这里为什么时间不一样，因为我们获取了三个类型，所以有时差；下面我们使用LocalDateTime进行转换时间
        System.out.println("使用LocalDateTime转换的日期："+localDateTime.toLocalDate());
        System.out.println("使用LocalDateTime转换的时间："+localDateTime.toLocalTime());

        System.out.println("================================================================================");
        /**
         * 反过来，通过指定的日期和时间创建LocalDateTime可以通过of()方法：
         */
        //自定义时间
        LocalDate localDate = LocalDate.of(2002,12,3);
        LocalTime localTime = LocalTime.of(20,30,27);
        LocalDateTime localDateTime1 = LocalDateTime.of(2019,3,23,8,19,21);

        System.out.println("输出自定义的日期："+localDate);
        System.out.println("输出自定义的时间："+localDate);
        System.out.println("输出自定义的日期时间："+localDateTime1);
        LocalDateTime localDateTime2 = LocalDateTime.of(localDate,localTime);
        System.out.println("组合了上面的localDate与localTime："+localDateTime2);

        System.out.println("================================================================================");
        //字符串格式的输入
        //"2019-11-19T15:16:17"
        LocalDateTime localDateTime3 = LocalDateTime.parse("2022-12-12T13:21:24");
        LocalDate localDate1 = LocalDate.parse("2019-11-19");
        LocalTime localTime1 = LocalTime.parse("12:32:12");
        System.out.println("使用字符串的类型定义的日期："+localDate1);
        System.out.println("使用字符串的类型定义的时间："+localTime1);
        System.out.println("使用字符串的类型定义的日期和时间："+localDateTime3);
        /**
         * 注意ISO 8601规定的日期和时间分隔符是T。标准格式如下：
         *      日期：yyyy-MM-dd
         *      时间：HH:mm:ss
         *      带毫秒的时间：HH:mm:ss.SSS
         *      日期和时间：yyyy-MM-dd'T'HH:mm:ss
         *      带毫秒的日期和时间：yyyy-MM-dd'T'HH:mm:ss.SSS
         *
         *自定义格式：DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         */

        System.out.println("======================================DateTimeFormatter==========================================");
        //自定义格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println(formatter.format(LocalDateTime.now()));

        //自定义格式解析
        LocalDateTime dt = LocalDateTime.parse("2003-11-12 12:32:33",formatter);
        System.out.println(dt);

        System.out.println("================================================================================");
        /**
         * LocalDateTime提供了对日期和时间进行加减的非常简单的链式调用：
         */
        System.out.println("调用上面自定义的时间："+localDateTime1);
        // 加5天减3小时:
        LocalDateTime ldt = localDateTime1.plusDays(5).minusHours(3);
        System.out.println("加5天减3小时后的日期时间:"+ldt);
        // 减1月:
        LocalDateTime ldt1 = localDateTime1.minusMonths(1);
        System.out.println("减去一个月之后的日期："+ldt1);

        System.out.println("================================================================================");
        /**
         * 对日期和时间进行调整则使用withXxx()方法，例如：withHour(15)会把10:11:12变为15:11:12：
         *      调整年：withYear()
         *      调整月：withMonth()
         *      调整日：withDayOfMonth()
         *      调整时：withHour()
         *      调整分：withMinute()
         *      调整秒：withSecond()
         */
        //对日期和时间进行调整
        LocalDateTime ldt2 = LocalDateTime.of(2002,1,12,12,13,43);
        System.out.println("调整前的日期时间："+ldt2);
        // 日期变为31日:
        LocalDateTime ldt3 = ldt2.withDayOfMonth(31);
        System.out.println("日期变为31日:"+ldt3);
        // 月份变为9:
        LocalDateTime ldt4 = ldt3.withMonth(9);
        System.out.println("月份变为9:"+ldt4);

        System.out.println("================================================================================");
        /**
         * LocalDateTime还有一个通用的with()方法允许我们做更复杂的运算。例如：
         */
        // 本月第一天0:00时刻:
        LocalDateTime firstDay = LocalDate.now().withDayOfMonth(1).atStartOfDay();
        System.out.println("本月第一天0:00时刻:"+firstDay);

        // 本月最后1天:
        LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
        System.out.println("本月最后1天:"+lastDay);

        // 下月第1天:
        LocalDate nextMonthFirstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfNextMonth());
        System.out.println("下月第1天:"+nextMonthFirstDay);

        // 本月第1个周一:
        LocalDate firstWeekday = LocalDate.now().with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
        System.out.println("本月第1个周一:"+firstWeekday);

        System.out.println("================================================================================");
        /**
         * 要判断两个LocalDateTime的先后，可以使用isBefore()、isAfter()方法，对于LocalDate和LocalTime类似：
         */
        LocalDateTime ldt5 = LocalDateTime.now();
        System.out.println(ldt5.isBefore(ldt2));
        System.out.println(LocalDate.now().isBefore(LocalDate.of(2024,1,2)));       //判断自定义日期是否在之前
        System.out.println(LocalTime.now().isAfter(LocalTime.parse("23:21:43")));       //判断自定义时间是否在之后

        System.out.println("===================================Duration和Period==============================");
        /**
         * Duration表示两个时刻之间的时间间隔。另一个类似的Period表示两个日期之间的天数：
         */
        LocalDateTime start = LocalDateTime.of(2023,12,3,00,23,43);
        LocalDateTime end = LocalDateTime.of(2022,12,21,12,46,7);

        Duration d = Duration.between(start,end);
        System.out.println(d);  //PT-8315H-37M-36S      8315小时，37分钟，36秒
        Period p = LocalDate.of(2019,11,19).until(LocalDate.of(2020,1,9));
        System.out.println(p);      //P1M21D        1个月21天
        System.out.println("===========================================================");
        /**
         * Duration和Period的表示方法也符合ISO 8601的格式，它以P...T...的形式表示，P...T之间表示日期间隔，T后面表示时间间隔。
         * 如果是PT...的格式表示仅有时间间隔。利用ofXxx()或者parse()方法也可以直接创建Duration：
         */
        Duration d1 = Duration.ofHours(10);
        Duration d2 = Duration.parse("P1DT2H3M");
        System.out.println(d1);
        System.out.println(d2);

        /**
         * 小结：
         *      Java 8引入了新的日期和时间API，它们是不变类，默认按ISO 8601标准格式化和解析；
         *          使用LocalDateTime可以非常方便地对日期和时间进行加减，或者调整日期和时间，它总是返回新对象；
         *          使用isBefore()和isAfter()可以判断日期和时间的先后；
         *          使用Duration和Period可以表示两个日期和时间的“区间间隔”。
         */
    }
}
